package com.iot.mqtt.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.iot.common.constant.Constants;
import com.iot.common.constant.UserConstants;
import com.iot.common.core.domain.entity.SysDictData;
import com.iot.common.utils.DateUtils;
import com.iot.common.utils.DictUtils;
import com.iot.common.utils.HexUtils;
import com.iot.common.utils.StringUtils;
import com.iot.device.domain.GasEvent;
import com.iot.device.domain.GasClient;
import com.iot.device.domain.GasEventOrigin;
import com.iot.device.service.IGasEventService;
import com.iot.device.service.IGasClientService;
import com.iot.device.service.IGasEventOriginService;
import com.iot.device.utils.LocationUtil;
import com.iot.mqtt.callback.GasBeijingMqttCallback;
import com.iot.websocket.Topic;
import com.iot.websocket.WebSocketMessageSender;
import com.iot.websocket.message.EventMsgMessage;
import com.iot.websocket.message.GpsMessage;
import com.iot.websocket.message.VbatMessage;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 设备消息处理器
 * @author Cao.ning
 * @date 2022/11/11
 */
@Component
public class GasClientHandler {
    private static final Logger logger = LoggerFactory.getLogger(GasClientHandler.class);

    @Autowired
    public ThreadPoolTaskExecutor threadPoolTaskExecutor;
    @Autowired
    public IGasClientService gasClientService;
    @Autowired
    public IGasEventService gasEventService;
    @Autowired
    public IGasEventOriginService gasEventOriginService;
    @Autowired
    public GasBeijingMqttCallback gasBeijingMqttCallback;

    /**
     * 处理消息
     * @param topic
     * @param message
     */
    public void handleMessage(String topic, MqttMessage message){
        // 必须用线程池处理，mqtt消息是单线程，处理完一个后才处理下一个，避免消息多了处理不了多余消息
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            public void run() {
                logger.info("收到燃气管道监测设备消息：{}， {}", topic, message);
                try {
                    String[] topicStrs = topic.split("/");
                    String clientNo = topicStrs[1];
                    if(StringUtils.isEmpty(clientNo)){
                        return;
                    }
                    if(message == null){
                        return;
                    }
                    Date now = new Date();
                    GasClient gasClient = gasClientService.selectGasClientByClientNo(clientNo);
                    if(gasClient == null){
                        // 如果是新注册的设备
                        gasClient = new GasClient();
                        gasClient.setClientNo(clientNo);
                        gasClient.setAddTime(now);
                        gasClient.setLastTime(now);
                        gasClient.setOnlineTimes(0L);
                        gasClient.setRemark("设备自动注册");
                        gasClient.setAddress("-");
                        gasClient.setClientName(clientNo);
                        gasClient.setCreateBy("autoRegister");
                        gasClient.setUserId(1L);
                        gasClient.setOrgId(200L);
                        gasClient.setInstallType(Constants.GAS_INSTALL_VERTICAL);
                        gasClient.setLongitude(BigDecimal.valueOf(120.473013));
                        gasClient.setLatitude(BigDecimal.valueOf(36.146107));
                        gasClientService.insertGasClient(gasClient);
                    }
                    gasClient.setClientNo(clientNo);
                    AlertEventData alertEventData = analyseData(gasClient, new String(message.getPayload(), "UTF-8"));
                    if(alertEventData != null && alertEventData.getGasEventOrigin() != null){
                        gasEventOriginService.insertGasEventOrigin(alertEventData.getGasEventOrigin());
                    }
                    if(alertEventData != null && !alertEventData.getEventList().isEmpty()){
                        int c = gasEventService.batchInsertAlertEvent(alertEventData.getEventList());
                    }
                    alertEventData = null;
                    gasClient.setLastTime(now);
                    gasClientService.updateGasClient(gasClient);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        });
    }



    public static class AlertEventData {
        private GasEventOrigin eventOrigin;
        private GasEvent alertEvent;
        private List<GasEvent> eventList = new ArrayList<>();

        public AlertEventData() {
        }

        public AlertEventData(GasEventOrigin eventOrigin) {
            this.eventOrigin = eventOrigin;
        }

        public GasEventOrigin getGasEventOrigin() {
            return eventOrigin;
        }

        public void setGasEventOrigin(GasEventOrigin eventOrigin) {
            this.eventOrigin = eventOrigin;
        }

        public GasEvent getAlertEvent() {
            return alertEvent;
        }

        public void setAlertEvent(GasEvent alertEvent) {
            this.alertEvent = alertEvent;
        }

        public List<GasEvent> getEventList() {
            return eventList;
        }

        public void setEventList(List<GasEvent> eventList) {
            this.eventList = eventList;
        }

        public void addEvent(GasEvent event) {
            this.eventList.add(event);
        }
    }

    public AlertEventData analyseData(GasClient gasClient, String message){
        if(message.contains("cmdcnt=")){
            //
            return null;
        }
        Date now = new Date();
        gasClient.setLastTime(DateUtils.getNowDate());
        if(HexUtils.isHex(message)){
            // 原始数据
            if(message.startsWith("5A5A"))
            {
                // String msg = msgContent.substring(12, msgContent.length() - 4).replace(" ", "").replace("\r", "").replace("\n", "");

                //String timestamp = HexUtils.reverseHex(HexUtils.longToHex(now.getTime()));
                //String samplingRate = HexUtils.reverseHex(HexUtils.longToHex(100));
                // String text = "5A5A" + timestamp + samplingRate + message.substring(4, message.length());

                byte[] bytes = HexUtils.hexStringToByte(message.substring(24, message.length() - 1));
                JSONArray floats = HexUtils.bytes2FloatArray(bytes);

                String eventId = HexUtils.reverseHex(message.substring(20, 24));

                String time = HexUtils.reverseHex(message.substring(4, 16));

                GasEventOrigin gasEventOrigin = new GasEventOrigin();
                gasEventOrigin.setEventId(1L);//TODO 这里需要获取eventId 上传的数据等待 冉 修改
                gasEventOrigin.setOriginEventId(Long.parseLong(eventId, 16));
                gasEventOrigin.setData(floats.toJSONString());
                gasEventOrigin.setHexData(message);
                gasEventOrigin.setClientNo(gasClient.getClientNo());
                gasEventOrigin.setCreateTime(new Date(Long.parseLong(time, 16)));
                gasEventOriginService.insertGasEventOrigin(gasEventOrigin);
                logger.debug("燃气MQTT原始数据已保存");

                SysDictData dictData = DictUtils.getDictData(Constants.GAS_PARAM, Constants.SEND_TO_BEIJING);
                if(dictData != null && UserConstants.DICT_NORMAL.equals(dictData.getStatus())){
                    gasBeijingMqttCallback.publish(String.format(GasBeijingMqttCallback.SEND_TOPIC, gasClient.getClientNo()), 2, message);
                    logger.info("燃气MQTT数据已发送，message: {}", message);
                    /*String binText = HexUtils.hexString2binString(text);
                    if(beijingMqttCallback.getClient().isConnected()){
                        beijingMqttCallback.publish(String.format(BeijingMqttCallback.SEND_TOPIC, clientNo), 2, binText);
                        logger.info("燃气MQTT数据已发送，text: {}, binText: {}", text, binText);
                    }*/
                }else{
                    logger.info("燃气MQTT数据不发送，message: {}", message);
                }
            }
            return null;
        }

        if(message.toLowerCase().contains("vbat"))
        {
            String[] data = message.split("=");
            // 电压
            //Vbat=11.393702,Temp=31.125000
            if(gasClient != null)
            {
                gasClient.setVbat(data[1]);
                WebSocketMessageSender.send(VbatMessage.getInstance(Topic.GAS_VBAT, gasClient.getClientNo(), data[1]));
            }
        }
        // 温度
        else if(message.toLowerCase().startsWith("temp"))
        {
//            String[] data = msgContent.split("=");
//            GasClientBattery clientBattery = new GasClientBattery();
//            clientBattery.setClientNo(clientNo);
//            clientBattery.setTemp(Float.parseFloat(data[1]));
//            gasClientBatteryService.insertGasClientBattery(clientBattery);
        }
        // 指令回复
        else if(message.contains("----------------------") || message.equals("restore PARA")
                || message.startsWith("admin,cclk") || message.startsWith("admin,coord")
                || message.startsWith("accu_") || message.startsWith("len="))
        {
            if(message.startsWith("admin,coord")){
                String[] msgs = message.split(",");
                if(msgs.length > 3 && StringUtils.isNotBlank(msgs[2]) && StringUtils.isNotBlank(msgs[3])){
                    String longitude = msgs[2];
                    String latitude = msgs[3];
                    if(StringUtils.isEmpty(gasClient.getAddress()) || "-".equals(gasClient.getAddress())){
                        com.alibaba.fastjson.JSONObject location = LocationUtil.baiduGeocoder(Float.parseFloat(longitude), Float.parseFloat(latitude)).getJSONObject("result");
                        StringBuilder address = new StringBuilder();
                        address.append(location.getString("formatted_address"))
                                .append("(")
                                .append(location.getString("sematic_description"))
                                .append(")");
                        gasClient.setAddress(address.toString());
                    }
                    gasClient.setLongitude(new BigDecimal(longitude));
                    gasClient.setLatitude(new BigDecimal(latitude));
                    // SpringUtils.getBean(IGasClientService.class).updateGasClient(gasClient);
                    JSONObject json = new JSONObject();
                    json.put("longitude", longitude);
                    json.put("latitude", latitude);
                    WebSocketMessageSender.send(GpsMessage.getInstance(Topic.GAS_GPS, gasClient.getClientNo(), json));
                }
            }
//            WebSocketManager.sendMessageCallback2Admin(MessageTypeEnum.CLIENT_DEBUG_MESSAGE.getValue() + gasClient.getClientNo(), msgContent);
        }
        else
        {
            String splitSparator = "\\r\\n";
            if(!message.contains(splitSparator)){
                splitSparator = "\\n";
                if(!message.contains(splitSparator)){
                    splitSparator = "\\r";
                }
            }
            String[] msgs = message.split(splitSparator);
            /*
                angleY=2.045653,angleX=-358.759460,angleZ=-0.019667,event_ID=83
                positionX=105.677956,positionY=4.577440,positionZ=1.308609,event_ID=84
                positionY=4.577440,positionX=0.000000,positionZ=1.308609,event_ID=85
                positionZ=1.308609,positionX=0.000000,positionY=0.000000,event_ID=86
                Ii=5.749379,event_ID=89
            */
            JSONObject position = new JSONObject();
            JSONObject ii = new JSONObject();
            JSONObject angel = new JSONObject();
            for(String msg : msgs) {
                if (StringUtils.isEmpty(msg)) {
                    continue;
                }
                GasEvent gasEvent = new GasEvent();
                gasEvent.setClientNo(gasClient.getClientNo());
                gasEvent.setEventTime(now);
                gasEvent.setEventDate(now);
                gasEvent.setOriginData(msg);
                float maxValue = 0;
                String maxValType = null;
                boolean isAlertEvent = true;
                if (msg.startsWith("position"))
                {
                    gasEvent.setEventType("position");
                    // 位移
                    String[] positionMsgs = msg.split(",");
                    for (String item : positionMsgs) {
                        String[] kv = item.split("=");
                        if (kv.length == 2) {
                            String key = kv[0];
                            String value = kv[1];
                            if (key.equals("event_ID")) {
                                gasEvent.setEventId(value);
                                continue;
                            }
                            if (value.split("\\.")[0].length() > 20) {
                                value = "0";
                            }
                            if (Math.abs(Float.parseFloat(value)) > Math.abs(maxValue)) {
                                maxValue = Float.parseFloat(value);
                                maxValType = key;
                            }
                            position.put(key, value);
                        }
                    }
                    position.put("positionMaxValue", maxValue);
                    position.put("positionMaxType", maxValType);
                }
                else if (msg.startsWith("Ii"))
                {
                    gasEvent.setEventType("Ii");
                    // 震动
                    String[] iiMsgs = msg.split(",");
                    for (String item : iiMsgs) {
                        String[] kv = item.split("=");
                        if (kv.length == 2) {
                            String key = kv[0];
                            String value = kv[1];
                            if (key.equals("event_ID")) {
                                gasEvent.setEventId(value);
                                continue;
                            }
                            if (value.split("\\.")[0].length() > 20) {
                                value = "0";
                            }
                            if (Math.abs(Float.parseFloat(value)) > Math.abs(maxValue)) {
                                maxValue = Float.parseFloat(value);
                                maxValType = key;
                            }
                            ii.put(key, value);
                        }
                    }
                    ii.put("iiMaxValue", maxValue);
                    ii.put("iiMaxType", maxValType);
                }
                else if (msg.startsWith("angle"))
                {
                    gasEvent.setEventType("angle");
                    // 倾斜
                    String[] angelMsgs = msg.split(",");
                    for (String item : angelMsgs) {
                        String[] kv = item.split("=");
                        if (kv.length == 2) {
                            String key = kv[0];
                            String value = kv[1];
                            if (key.equals("event_ID")) {
                                gasEvent.setEventId(value);
                                continue;
                            }
                            if (value.split("\\.")[0].length() > 20) {
                                value = "0";
                            }
                            if (Math.abs(Float.parseFloat(value)) > Math.abs(maxValue)) {
                                maxValue = Float.parseFloat(value);
                                maxValType = key;
                            }
                            angel.put(key, value);
                        }
                    }
                    angel.put("angelMaxValue", maxValue);
                    angel.put("angelMaxType", maxValType);
                }
                else
                {
                    isAlertEvent = false;
                }
                if(isAlertEvent){
                    gasEvent.setMaxValue(maxValue);
                    gasEvent.setMaxValueType(maxValType);
                    gasEventService.insertGasEvent(gasEvent);

                    WebSocketMessageSender.send(EventMsgMessage.getInstance(Topic.GAS_EVENT_MSG, gasClient.getOrgId(), JSON.parseObject(JSON.toJSONString(gasEvent))));
                }
            }
        }
        return null;
    }

    public static void main(String[] args) {
        Date now = new Date();
        String s = HexUtils.reverseHex(HexUtils.longToHex(now.getTime()));
        String s1 = HexUtils.longToHex(100);
        System.out.println(s + "--" + s1);
        String message = "5A5A4B90B18B890164000F00D368BF645F034000ED387D3F9E2C493D34EF0FBD53777E3F2E38413D5E2D00BD58407D3F861D3D3D88DB23BD79FE7C3F841E413D7CD61FBDF3B77C3F72294D3D1CDD0FBDE77D7D3F3E1A353D10FB0FBD95FE7C3F701A3D3D6ADB1BBDE5F77D3F763C4D3DC80810BDB13B7D3F7827453D36E717BDCC7B7D3F3027413DE2F413BDBB797C3FEE244D3DC0CB17BDC9BA7D3F6E2F453DFEFC13BD24797D3F4228413DD00108BD55807D3F52213D3D46E423BD3EB77D3FDC30453D3A0E04BDABBB7D3F122F453DAEF817BD3EB87D3F6C2C413DDA0E04BD28377D3F542D493DD4F707BD3E007D3FCE1D413DDCCD27BD00FA7D3F822F413DF80E0CBD77007D3FA415393DBCD71FBD5CC17C3F7A11393DB0CA23BDCC7A7D3FA02B453D42F413BD5A007D3FB8193D3DCCD223BD22B77D3FEE34493D4C0908BD8FBB7D3F2633493DC0F31BBDE87B7D3F1C233D3DD0F90FBDF1BA7C3F241C413DFCDE0FBD593F7D3FF621413DE8DA23BDB13B7D3F7827453D36E717BDCB7C7D3FC0223D3D82F513BD99BC7C3F821F453D6ED11BBDCE3C7D3FF41E3D3DC4EC13BD567E7D3F322A453D06E323BD9A7F7C3F660E393D92CA1BBD71BE7D3FEC29413DB0F01FBD57417D3F1619393D28DC23BD747E7D3F1E26413DF4E71FBDCB7C7D3FC0223D3D82F513BDCBB87D3F4C384D3DBEFB13BDB03D7D3F981E3D3D76E817BD577D7D3FA02E493D66E223BD3EB87D3F6C2C413DDA0E04BDB6BB7C3FDC1F453DBED517BD18797E3F7837413DC02408BDAF7A7D3FB22F493D52EF17BD03BA7D3FB42B413D3C060CBDABBB7D3F122F453DAEF817BDCF3B7D3F6423413D24EC13BD5A007D3FB8193D3DCCD223BD0BF97C3FBC24453D68EB0BBD76027D3FC60C313DFCD81FBDCD797D3F0E30493DA2F313BDC4FD7D3FEC25393D9A0714BD0C427C3FAE11413D0AAB2FBDEC3A7D3FC023413D74F00FBD20027D3F02193D3D2ECA2BBD3EB77D3FDC30453D3A0E04BD943D7D3FAE22413D88E31BBD7AB47D3F0036493D722CF8BC06797D3F562C453DE0FC0BBDEC3A7D3FC023413D74F00FBDC07A7E3FD63A453D321714BD00F97D3FF233453D580E0CBD5A5A";
        byte[] bytes = HexUtils.hexStringToByte(message.substring(24, message.length() - 1));
        JSONArray floats = HexUtils.bytes2FloatArray(bytes);
        System.out.println(floats);
        String eventId = HexUtils.reverseHex(message.substring(20, 24));
        System.out.println(Long.parseLong(eventId, 16));
        String time = HexUtils.reverseHex(message.substring(4, 16));
        System.out.println(Long.parseLong(time, 16));
    }
}
